package base.map.findPath
{
	import flash.utils.Dictionary;

	/**
	 *根据单元网格生成矩形导航网络 
	 * @author devin
	 * 
	 */	
	public class FindPathBuildNode
	{
		/**
		 *单元格最大宽
		 */		
		private var _width:int;
		/**
		 *单元格最大高 
		 */		
		private var _height:int;
		/**
		 *地图所有单元格集 
		 */		
		private var _findPathCells:Array;
		/**
		 *打开的单元网格集(指可被划分但目前未被划分过的)
		 */
		private var _openCells:Dictionary=new Dictionary(true);
		/**
		 *最大跨越通行地形高度 
		 */		
		private var _walkableHeight:int;
		
		/**
		 *最大穿越通行地形高度 
		 */		
		private var _walkableBottom:int;
		
		public function FindPathBuildNode(findPathCells:Array, height:int, width:int, walkableHeight:int, walkableBottom:int)
		{
			_findPathCells=findPathCells;
			_width=width;
			_height=height;
			_walkableHeight=walkableHeight;
			_walkableBottom=walkableBottom;
		}
		
		/**
		 *生成矩形导航网格
		 * @return 导航网格节点集
		 * 
		 */
		public function buildNode():Vector.<FindPathNode>
		{
			var findPathNodes:Vector.<FindPathNode>=new Vector.<FindPathNode>();
			
			//整理打开的单元格集
			for(var w:int=0;w<_width;w++)
			{
				for(var h:int=0;h<_height;h++)
				{
					var findPathCell:FindPathCell=_findPathCells[w][h];
					if(findPathCell.walkable)
					{
						if(_openCells[w]==null)_openCells[w]=new Dictionary(true);
						_openCells[w][h]=findPathCell;
					}
				}
			}

			var startCell:FindPathCell;//一个新的寻路网格起始单元格
			var findPathBuildNodeDirection:FindPathBuildNodeDirection=new FindPathBuildNodeDirection();//合并方向
			while(true)
			{
				startCell=null;
				findPathBuildNodeDirection.reset();
				
				//设置下一个合并起始点
				for each(var dic:Object in _openCells)
				{
					for each(var obj:Object in dic)
					{
						startCell=obj as FindPathCell;
						break;
					}
					if(startCell==null)continue;
					break
				}
				if(startCell==null)break;//如果找不到合并起始点，则退出，表示所有的已合并完毕
				
				//创建一个新的寻路网格
				var findPathNode:FindPathNode=new FindPathNode();
				findPathNode.tileHeight=startCell.height;
				findPathNode.x=startCell.x;
				findPathNode.y=startCell.y;
				delete _openCells[findPathNode.x][findPathNode.y];
				findPathNodes.push(findPathNode);
				var isNext:Boolean=true;
				while(true)
				{
					switch(findPathBuildNodeDirection.nextDirection())
					{
						case FindPathBuildNodeDirection.BOTTOM:
							var isMerge:Boolean=true;
							if(_openCells[findPathNode.x-1]!=null && _openCells[findPathNode.x-1][findPathNode.y+findPathNode.height]!=null)
							{//如果当前检查的单元格的下一行的左边格为打开格，那么这整个寻路网络就不能向下合并了
								findPathBuildNodeDirection.addDisableDirection(FindPathBuildNodeDirection.BOTTOM);//禁用向下合并方向
								isMerge=false;
								break;
							}
							
							for(var i:int=0;i<findPathNode.width;i++)
							{
								if(_openCells[findPathNode.x+i]==null || _openCells[findPathNode.x+i][findPathNode.y+findPathNode.height]==null || startCell.height!=_openCells[findPathNode.x+i][findPathNode.y+findPathNode.height].height)
								{//如果当前检查的单元格的下一行的格不为打开格或者地形高度不相同，那么这整个寻路网络就不能向下合并了
									findPathBuildNodeDirection.addDisableDirection(FindPathBuildNodeDirection.BOTTOM);//禁用向下合并方向
									isMerge=false;
									break;
								}
							}
							if(isMerge)
							{//可合并
								//关闭掉可合并的单元格
								for(i=0;i<findPathNode.width;i++)
								{
									delete _openCells[findPathNode.x+i][findPathNode.y+findPathNode.height];
								}
								findPathNode.height+=1;//增加一个高度，表示这个寻路网格向下合并了一行
							}
							break;
						case FindPathBuildNodeDirection.RIGHT:
							isMerge=true;
							for(i=0;i<findPathNode.height;i++)
							{
								if(_openCells[findPathNode.x+findPathNode.width]==null || _openCells[findPathNode.x+findPathNode.width][findPathNode.y+i]==null || startCell.height!=_openCells[findPathNode.x+findPathNode.width][findPathNode.y+i].height)
								{
									findPathBuildNodeDirection.addDisableDirection(FindPathBuildNodeDirection.RIGHT);//禁用向右合并方向
									isMerge=false;
								}
							}
							if(isMerge)
							{//可合并
								for(i=0;i<findPathNode.height;i++)
								{
									delete _openCells[findPathNode.x+findPathNode.width][findPathNode.y+i];
								}
								findPathNode.width+=1;//增加一个宽度，表示这个寻路网格向右合并了一列
							}
							break;
						case FindPathBuildNodeDirection.NOTHING:
							isNext=false;
							break;
					}
					if(!isNext)
					{//如果无法继续下一步合并，说明当前寻路网格已经不能再进行任何合并了，直接返回
						break;
					}
				}
			}
			return createLinks(findPathNodes);
		}
		
		/**
		 *建立导航网格之间的连接 
		 * @param findPathNodes
		 * @return 
		 * 
		 */		
		private function createLinks(findPathNodes:Vector.<FindPathNode>):Vector.<FindPathNode>
		{
			for each(var findPathNode:FindPathNode in findPathNodes)
			{
				for each(var findPathNodeTaget:FindPathNode in findPathNodes)
				{
					if(findPathNode==findPathNodeTaget
						|| findPathNodeTaget.x>(findPathNode.x+findPathNode.width)
						|| findPathNodeTaget.y>(findPathNode.y+findPathNode.height)
						|| findPathNode.x>(findPathNodeTaget.x+findPathNodeTaget.width)
						|| findPathNode.y>(findPathNodeTaget.y+findPathNodeTaget.height)
						|| (findPathNodeTaget.x+findPathNodeTaget.width<=findPathNode.x && findPathNodeTaget.y+findPathNodeTaget.height<=findPathNode.y)
						|| (findPathNodeTaget.x+findPathNodeTaget.width<=findPathNode.x && findPathNodeTaget.y>=findPathNode.y+findPathNode.height)
						|| (findPathNodeTaget.x>=(findPathNode.x+findPathNode.width) && findPathNodeTaget.y+findPathNodeTaget.height<=findPathNode.y)
						|| (findPathNodeTaget.x>=(findPathNode.x+findPathNode.width) && findPathNodeTaget.y>=findPathNode.y+findPathNode.height)
						|| Math.abs(findPathNode.tileHeight-findPathNodeTaget.tileHeight)>_walkableHeight
					)continue;
					findPathNode.addLinkNode(findPathNodeTaget);
				}
			}
			return findPathNodes;
		}
		
		public function dispose():void
		{
			_findPathCells=null;
			_openCells=null;
		}
	}
}